package com.cnap.config;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.URLUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.github.dockerjava.transport.DockerHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.time.Duration;

/**
 * docker配置类
 *
 * @author xc
 **/
@Configuration
public class DockerConfig {

    private static final String HARBOR_API_V2_DELETE_ARTIFACTS_PATH = "/api/v2.0/projects/{}/repositories/{}/artifacts/{}";
    private static final String HARBOR_API_V2_DELETE_REPOSITORY_PATH = "/api/v2.0/projects/{}/repositories/{}";

    @Value("${dockerInfo.host}")
    private String dockerHost;
    @Value("${dockerInfo.registry.user-name}")
    private String registryUserName;
    @Value("${dockerInfo.registry.password}")
    private String registryPassword;
    @Value("${dockerInfo.registry.url}")
    private String registryUrl;
    @Value("${dockerInfo.registry.prefix}")
    private String registryPrefix;
    private DockerClient dockerClient;

    /**
     * get
     *
     * @return DockerHost
     */
    public String getDockerHost() {
        return dockerHost;
    }

    /**
     * set
     *
     * @param dockerHost dockerHost
     */
    public void setDockerHost(String dockerHost) {
        this.dockerHost = dockerHost;
    }

    /**
     * get
     *
     * @return RegistryUserName
     */
    public String getRegistryUserName() {
        return registryUserName;
    }

    /**
     * set
     *
     * @param registryUserName registryUserName
     */
    public void setRegistryUserName(String registryUserName) {
        this.registryUserName = registryUserName;
    }

    /**
     * get
     *
     * @return RegistryPassword
     */
    public String getRegistryPassword() {
        return registryPassword;
    }

    /**
     * set
     *
     * @param registryPassword registryPassword
     */
    public void setRegistryPassword(String registryPassword) {
        this.registryPassword = registryPassword;
    }

    /**
     * get
     *
     * @return RegistryUrl
     */
    public String getRegistryUrl() {
        return registryUrl;
    }

    /**
     * set
     *
     * @param registryUrl registryUrl
     */
    public void setRegistryUrl(String registryUrl) {
        this.registryUrl = registryUrl;
    }

    /**
     * get
     *
     * @return RegistryPrefix
     */
    public String getRegistryPrefix() {
        return registryPrefix;
    }

    /**
     * set
     *
     * @param registryPrefix registryPrefix
     */
    public void setRegistryPrefix(String registryPrefix) {
        this.registryPrefix = registryPrefix;
    }

    /**
     * get
     *
     * @return DockerClient
     */
    public DockerClient getDockerClient() {
        return dockerClient;
    }

    /**
     * set
     *
     * @param dockerClient dockerClient
     */
    public void setDockerClient(DockerClient dockerClient) {
        this.dockerClient = dockerClient;
    }

    @PostConstruct
    public void initDockerClient() {
        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(this.dockerHost)
                .withDockerTlsVerify(false) // 不使用tls认证
                .withRegistryUrl(this.registryUrl)
                .withRegistryUsername(this.registryUserName)
                .withRegistryPassword(this.registryPassword)
                .build();
        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
                .dockerHost(config.getDockerHost())
                .sslConfig(config.getSSLConfig())
                .maxConnections(100)
                .connectionTimeout(Duration.ofSeconds(30))
                .responseTimeout(Duration.ofSeconds(45))
                .build();
        this.dockerClient = DockerClientImpl.getInstance(config, httpClient);
    }

    /**
     * 获取harbor的token，用于发送请求
     *
     * @return token
     */
    public String getHarborToken() {
        String joinStr = String.join(":", registryUserName, registryPassword);
        return "Basic " + Base64Encoder.encode(joinStr);
    }

    /**
     * 获取镜像删除的url路径
     *
     * @param imageFullName 镜像全称，172.171.11.67/test/admin/nginx:stable
     * @return url https://172.171.11.67/api/v2.0/projects/test/repositories/admin%252Fnginx/artifacts/stable
     */
    public String getDeleteImageUrl(String imageFullName) {
        String projectName = registryPrefix.split("/")[1];
        String repositoryName = imageFullName.replace(registryUrl, "").split(":")[0];
        String tag = imageFullName.replace(registryUrl, "").split(":")[1];

        /**
         * / -> %2F
         */
        String firstEncode = URLUtil.encodeQuery(repositoryName.replace("/" + projectName + "/", ""));
        /**
         * %2F -> %252F
         */
        String secondEncode = URLUtil.encodeQuery(firstEncode);

        String baseUrl = CharSequenceUtil.format(HARBOR_API_V2_DELETE_ARTIFACTS_PATH, projectName, secondEncode, tag);

        return "https://" + registryUrl + baseUrl;
    }

    /**
     * 获取删除镜像所在respo的url，当repo里面没有镜像时，需要删除啊repo
     *
     * @param imageFullName 镜像全称，172.171.11.67/test/admin/nginx:stable
     * @return https://172.171.11.67/api/v2.0/projects/test/repositories/admin%252Fnginx
     */
    public String getDeleteRepositoryUrl(String imageFullName) {
        String projectName = registryPrefix.split("/")[1];
        String repositoryName = imageFullName.replace(registryUrl, "").split(":")[0];

        /**
         * / -> %2F
         */
        String firstEncode = URLUtil.encodeQuery(repositoryName.replace("/" + projectName + "/", ""));
        /**
         * %2F -> %252F
         */
        String secondEncode = URLUtil.encodeQuery(firstEncode);

        String baseUrl = CharSequenceUtil.format(HARBOR_API_V2_DELETE_REPOSITORY_PATH, projectName, secondEncode);

        return "https://" + registryUrl + baseUrl;
    }

}
